﻿using System.Collections.Generic;
using System.Threading;
using LogSystem;
using Pathfinding;
using Pathfinding.Util;
using UnityEngine;
using Yoozoo.Mars.Got;
using TimerCallback = Yoozoo.Mars.Got.TimerCallback;

namespace Yoozoo.Gameplay.City
{
    public class CityAreaNpcController : CityRealAiNpcController
    {
        private TimerCallback _getOnTransportAniComplete;
        private TimerCallback _getOffTransportAniComplete;
        private TimerCallback _getOnBusAniComplete;
        private TimerCallback _getOffBusAniComplete;

        // 所属营业巴士
        private int _belongBusIndex = -1;
        // 营业类型
        public CityBusinessType BusinessType => _businessType;
        private CityBusinessType _businessType = CityBusinessType.None;
        // 是否是恢复营业状态的顾客
        private bool _isRestoreCustomer = false;
        private bool _isJumpToRoomCustomer = false;
        
        public override CityRealNpcType NpcType
        {
            get { return CityRealNpcType.AreaNpc; }
        }
        
        public CityAreaNpcController(int birthContainerId, CityRealAiRoleInfoConfig roleInfoConfig, Vector3 birthWorldPos) : base(birthContainerId, roleInfoConfig, birthWorldPos)
        {
            IsAlive = true;
            _getOnTransportAniComplete = GetOnTransportAniComplete;
            _getOffTransportAniComplete = GetOffTransportAniComplete;
            _getOnBusAniComplete = GettOnBusAniComplete;
            _getOffBusAniComplete = GettOffBusAniComplete;
        }

        protected override void LoadRoleObjComplete()
        {
            base.LoadRoleObjComplete();
            _roleObj.SetLayerRecursively(LayerMask.NameToLayer("LOD1_2"));
            // if(model)
            //     model.SetCullingLayer(CityRealAiManager.GetInstance().LimitShowState ? 0 : LayerMask.NameToLayer("city"));
            var ins = CityRealAiManager.GetInstance();
            if(model)
                model.SetCullingLayer(ins.RoofShowState && ins.LimitShowState? CityRealAiConst.NpcHideLayerMask : CityRealAiConst.NpcShowLayerMask);
            Seeker.UpdatePos(BirthWorldPos);
            Seeker.SetIsInRoomAction(false);
            UpdateSunLight(false);
            Seeker.SetupStartEndExactnessType(StartEndModifier.Exactness.SnapToNode);
            if (_delayFirstStartTime <= 0)
            {
                _delayFirstStartTime = 0.001f;
            }
            Timers.inst.Add(_delayFirstStartTime, 1, (o) =>
            {
                if (IsUnlockAreaPerform)
                {
                    return;
                }
                if (RoleClassType == (int)CityRealNpcClassType.Customer)
                {
                    _customerBusLeave = false;
                    // 闪现到房间
                    if (_isJumpToRoomCustomer)
                    {
                        _isJumpToRoomCustomer = false;
                        ExecuteNpcJumpToRoom(BirthWorldPos);
                    }
                    // 顾客
                    else if (_isRestoreCustomer)
                    {
                        // 顾客直接随机到内城开始执行消费行为（恢复营业状态流程）
                        ExecuteRestoreCustomer(BirthWorldPos);
                    }
                    else
                    {
                        // 顾客从巴士下车去排队（正常流程）
                        ExecuteGetOffBus(BirthWorldPos);
                    }
                }
                else if (RoleClassType == (int)CityRealNpcClassType.Staff)
                {
                    bool canExecute = RandomExecuteEventTree(0);
                    if (canExecute)
                    {
                        return;
                    }
                
                    RandomExecuteIdleEvent(0);
                }
                else if (TreeConfig.event_tree_id != _cfgMgr.EmptyEventTreeCfg.event_tree_id && TreeType == CityRealEventTreeType.SpecialEventTree)
                {
                    ExecuteEventTreePosition();
                }
                else
                {
                    TryExecuteEventTree();
                }
            });
        }

        protected override void SearchPathPartialComplete()
        {
            if (_containerMgr is CityRealAiAreaManager) // 在区域内，寻路失败
            {
                if (IsUnlockAreaPerform)
                {
                    // 区域解锁表演的顾客和雇员，重新寻路
                    RestartEventTree();
                }
                else if (RoleClassType == (int)CityRealNpcClassType.Staff)
                {
                    // 区域里的雇员不处理
                }
                else
                {
                    //如果是区域内游荡小人，不进屋，只在区域内随机点
                    var excludeRoomId = 0;
                    if (_moveToRoom != null)
                    {
                        excludeRoomId = _moveToRoom.ContainerId;
                    }
                    EndEventTree();
                    TryExecuteEventTree(excludeRoomId);
                }
                
            }
            else if (_containerMgr is CityRealAiRoomManager roomMgr)
            {
                // 理论上，在房间内不应该可以寻路失败，给他重置一下位置，再重新寻找一个可执行的事件
                Seeker.UpdatePos(roomMgr.GetWorldPos(roomMgr.GetRandomBirthLocalPos()));
                EndEventTree();
                TryExecuteEventTree();
            }
        }

        protected override void SearchPathErrorComplete()
        {
            if (_containerMgr is CityRealAiAreaManager)
            {
                //如果是区域内游荡小人，不进屋，只在区域内随机点
                if (RoleClassType == (int)CityRealNpcClassType.Staff)
                {
                    
                    return;    
                }
                
                var treeArray = RoleConfig.faulttolerance_tree_array;
            
                var totalWeight = 0f;
                for (int i = 0; i < treeArray.Length; i++)
                {
                    var treeCfg = treeArray[i];
                    totalWeight += treeCfg.y;
                }

                var executeTreeCfg = Vector2.zero;
                int cursor = 0;
                int random = Random.Range(0, (int) totalWeight);
                for (int i = 0; i < treeArray.Length; i++)
                {
                    var treeCfg = treeArray[i];
                    cursor += (int) treeCfg.y;
                    if(cursor > random)
                    {
                        executeTreeCfg = treeCfg;
                        break;
                    }
                }

                TreeConfig = _cfgMgr.GetAiEventTreeConfig((int)executeTreeCfg.x);
                TreeState = CityRealEventTreeState.WaitMoveRoom;
                TreeType = CityRealEventTreeType.SerarchPathFailedEventTree;
                TreeIsInterrupt = TreeConfig.is_interrupt;
                ExecuteEventTreePosition();
            }
            // 理论上，在房间内不应该可以寻路失败，但是他竟然在房间内，重置位置还多次寻路失败，这只能怀疑寻路有问题了。
        }

        public void SetBusinessType(CityBusinessType businessType)
        {
            _businessType = businessType;
        }
        
        public void SetBusIndex(int busIndex)
        {
            _belongBusIndex = busIndex;
        }

        public void SetIsRestoreCustomer(bool isRestore)
        {
            _isRestoreCustomer = isRestore;
        }

        public void SetupIsJumpToRoomCustomer(bool isJumpToRoomCustomer)
        {
            _isJumpToRoomCustomer = isJumpToRoomCustomer;
        }

        public void ExecuteRestoreCustomer(Vector3 worldPos)
        {
            if (_executedCostRoleType == null || _costRoleTypeList == null)
            {
                _executedCostRoleType = new List<int>();
                
                _costRoleTypeList = new List<Vector2Int>();
                // 固定行为
                if (RoleInfoInfoConfig.room_role_type != null)
                {
                    for (int i = 0; i < RoleInfoInfoConfig.room_role_type.Length; i++)
                    {
                        if (RoleInfoInfoConfig.room_role_type[i].x == ServerRoleInfo.buildingId)
                        {
                            _costRoleTypeList.Add(RoleInfoInfoConfig.room_role_type[i]);
                        }
                    }
                }
            }
            
            // 先搜索可以执行事件的房间
            if (_costRoleTypeList.Count > 0)
            {
                var area = CityRealAiManager.GetInstance().GetOrCreateArea(CityRealAiConst.WallAreaId);
                
                int index = -1;
                for (int i = 0; i < _costRoleTypeList.Count; i++)
                {
                    int buildingId = _costRoleTypeList[i].y;
                    // 房间等级 > 0
                    if (CityRealAiCSharpCallLuaManager.GetBuildingLevel(buildingId) > 0)
                    {
                        // 房间未满
                        var room = area.TryGetRoom(buildingId, 1);
                        if (room!=null && !room.IsFull)
                        {
                            index = i;
                            break;
                        }
                    }
                }

                // 在房间里执行事件
                if (index >= 0)
                {
                    var roleTypeCfg = _costRoleTypeList[index];
                    var roleConfig = CityRealAiManager.GetInstance().ConfigMgr.GetAiRoleConfig((int) roleTypeCfg.x);
                    var room = area.TryGetRoom((int)roleTypeCfg.y, 1);
                    var birthPos = room.GetWorldPos(room.GetRandomBirthLocalPos());
                    
                    // 设置npc
                    IsAlive = true;
                    Seeker.SetIsInRoomAction(true); // 切换室内寻路
                    Seeker.UpdatePos(birthPos);
                    // 切换房间
                    if (_containerMgr != null)
                    {
                        _containerMgr.RemoveNpcCtrl(RoleId, Uid);
                    }
                    room.AddNpcCtrl(this);
                    UpdateContainer(room);
                    UpdateSunLight(false);
                    _roleObj.SetActive(true);
                    
                    if (roleConfig.role_type > 0)
                    {
                        // 切换类型
                        UpdateRoleConfig(roleConfig);
                        if (_executedCostRoleType == null)
                        {
                            _executedCostRoleType = new List<int>();
                        }
                        _executedCostRoleType.Add(roleConfig.role_type);
                        
                        // 切换了新的RoleType
                        _costRoleTypeExecutedTimer = 0;
                        _hasExecutedCostTree = false;
                        // 随机新的行为
                        bool canExecute = RandomExecuteEventTree();
                        if (canExecute)
                        {
                            // 记录房间接待时长
                            _costRoleTypeExecuteDuration = GetEventTreeRoomReceptionTime();
                            return;
                        }
                    }
                }

            }

            // 没有搜索到可以执行事件的房间
            {
                
                if (Seeker)
                {
                    IsAlive = true;
                    Seeker.SetIsInRoomAction(false); // 切换区域寻路
                    Seeker.UpdatePos(worldPos);
                    _roleObj.SetActive(true);
                    TryExecuteEventTree();
                }
                else
                {
                    UnityEngine.Debug.LogWarning("Seeker is null");
                }
               
            }
        }

        public void UpdateBirthPosition(Vector3 birthPos)
        {
            BirthWorldPos = birthPos;
        }

        public void ExecuteNpcJumpToRoom(Vector3 worldPos)
        {
            IsAlive = true;
            Seeker.SetIsInRoomAction(true); // 切换室内寻路
            Seeker.UpdatePos(worldPos);
            Seeker.transform.localEulerAngles = new Vector3(0, 135f, 0);
            _roleObj.SetActive(true);
            TryExecuteEventTree();
        }

        public void ExecuteGetOffBus(Vector3 worldPos)
        {
            if (_containerMgr is CityRealAiWallManager)
            {
                IsAlive = true;
                Seeker.SetIsInRoomAction(true); // 切换室内寻路
                Seeker.UpdatePos(worldPos);
                Seeker.transform.localEulerAngles = new Vector3(0, 135f, 0);
                _roleObj.SetActive(true);
                Seeker.PlayAni(CityRealAiConst.NpcGetOffTransportAniName, Vector3.zero);
                Timers.inst.Add(CityRealAiConst.NpcGetOffTransportAniTime, 1, _getOffBusAniComplete);
            }
        }

        void GettOffBusAniComplete(object o)
        {
            // var wallRoom = _containerMgr as CityRealAiRoomManager;
            // wallRoom.TryStartMultiWaitQueue(this, out _waitIndex, out _waitQueueIndex);
            // _moveToRoom = wallRoom; // 强行设置当前房间，获取寻路点
            // // 执行检票排队行为
            // RandomExecuteWaitEventTree(true);
            
            // 不排队，直接去执行消费事件
            TryExecuteEventTree();
        }
        
        private void GetOnBusEventEnd()
        {
            Seeker.PlayAni(CityRealAiConst.NpcGetOnTransportAniName, new Vector3(0, -45f, 0));
            Timers.inst.Add(CityRealAiConst.NpcGetOnTransportAniTime, 1, _getOnBusAniComplete);
        }

        private void GettOnBusAniComplete(object o)
        {
            IsAlive = false;
            _roleObj.SetActive(false);

            CityRealAiWallManager wallMgr = CityRealAiManager.GetInstance().GetCityRealAiWallManager();
            wallMgr.CustomerBackToBus(_belongBusIndex, this);
        }

        public void ExecuteBackToBus()
        {
#if UNITY_EDITOR
            if (Seeker && Uid == Seeker.DEBUG_UID)
            {
                int aaa = 0;
            }
            
            // Debug.LogFormat(LogModule.CityAI, "ExecuteBackToBus = {0}, moveToRoom = {1}, Queue={2}, QIndex={3}", LogLevelType.Develop
                // , Uid, _moveToRoom==null?0:_moveToRoom.ContainerId, _waitQueueIndex, _waitIndex);
#endif
            _customerBusLeave = true;

            // 从排队队列中移除
            if (_moveToRoom != null)
            {
                _moveToRoom.TriggerWaitQueueLeave(this);
            }
            
            CityRealAiManager.GetInstance().HudMgr.OnHideProgressBar(Uid);
            CityRealAiManager.GetInstance().HudMgr.OnHideCommodity(Uid);
            EndEventTree();
            _moveToRoom = null;

            // CityRealAiWallManager wallMgr = CityRealAiManager.GetInstance().GetCityRealAiWallManager();
            // Seeker.InRoomStartMove(Uid, wallMgr.ContainerId, wallMgr.GetBusDownPointWorldPos(_belongBusIndex), CityRealAiConst.NpcDefaultMaxSpeed, wallMgr, GetOnBusEventEnd);
            MoveToBusStep();
        }

        void MoveToBusStep()
        {
#if UNITY_EDITOR
            if (Seeker && Uid==Seeker.DEBUG_UID)
            {
                int aaa = 0;
            }
#endif
            
            CityRealAiWallManager wallMgr = CityRealAiManager.GetInstance().GetCityRealAiWallManager();
            if (_containerMgr is CityRealAiWallManager)
            {
                // 已在城墙房间，直接回车上
                if (!Seeker.IsUseRoomNavigate)
                {
                    Seeker.SetIsInRoomAction(true);
                }
                UpdateSunLight(true);
                Seeker.InRoomStartMove(Uid, wallMgr.ContainerId, wallMgr.GetBusDownPointWorldPos(_belongBusIndex), CityRealAiConst.NpcLeaveMaxSpeed, wallMgr, GetOnBusEventEnd);
            }
            else if (_containerMgr is CityRealAiRoomManager roomManager)
            {
                // 在普通房间里，先出房间到城门区域
                if (!Seeker.IsUseRoomNavigate)
                {
                    Seeker.SetIsInRoomAction(true);
                }
                UpdateSunLight(true);
                Seeker.InRoomStartMove(Uid, CityRealAiConst.WallAreaId, roomManager.OutRoomLocalPos, CityRealAiConst.NpcLeaveMaxSpeed, roomManager, () =>
                    {
                        var inArea = CityRealAiManager.GetInstance().GetArea(CityRealAiConst.WallAreaId);
                        _containerMgr.RemoveNpcCtrl(RoleId, Uid);
                        UpdateContainer(inArea);
                        inArea.AddNpcCtrl(this);
                        MoveToBusStep();
                    });
            }
            else if (_containerMgr is CityRealAiAreaManager)
            {
                // 在区域里，向城门移动
                if (Seeker.IsUseRoomNavigate)
                {
                    Seeker.SetIsInRoomAction(false);
                }
                UpdateSunLight(true);
                Seeker.InRoomStartMove(Uid, CityRealAiConst.WallAreaId, wallMgr.OutRoomLocalPos, CityRealAiConst.NpcLeaveMaxSpeed, wallMgr, () =>
                    {
                        _containerMgr.RemoveNpcCtrl(RoleId, Uid);
                        UpdateContainer(wallMgr);
                        wallMgr.AddNpcCtrl(this);
                        MoveToBusStep();
                    });
            }
        }

//         public void ExecuteOccupyAreaPerform()
//         {
// #if UNITY_EDITOR
//             if (Seeker && Uid == Seeker.DEBUG_UID)
//             {
//                 int aaa = 0;
//             }
//             
//             // Debug.LogFormat(LogModule.CityAI, "ExecuteMoveToBackDoor = {0}, moveToRoom = {1}, Queue={2}, QIndex={3}", LogLevelType.Develop
//             // , Uid, _moveToRoom==null?0:_moveToRoom.ContainerId, _waitQueueIndex, _waitIndex);
// #endif
//             _occupyAreaPerformStep = 0;
//
//             // 隐藏HUD TODO
//             
//             EndEventTree();
//             _moveToRoom = null;
//             
//             
//             
//
//         }
//         
//         private void OcupyAreaPerformStep()
//         {
//             switch (_occupyAreaPerformStep)
//             {
//                 case 0:
//                     {
//                         // 庆祝动作
//                         
//                         Timers.inst.Add(1.5f, 1, o =>
//                         {
//                             
//                             // 下一步
//                             _occupyAreaPerformStep++;
//                             OcupyAreaPerformStep();
//                         });
//                     }
//                     break;
//
//                 case 1:
//                     {
//                         // 移动到后门
//                         CityRealAiWallManager wallMgr = CityRealAiManager.GetInstance().GetCityRealAiWallManager();
//                         if (!Seeker.IsUseRoomNavigate)
//                         {
//                             Seeker.SetIsInRoomAction(true);
//                         }
//                         UpdateSunLight(true);
//                         Seeker.InRoomStartMove(Uid, wallMgr.ContainerId, wallMgr.InRoomLocalPos2, CityRealAiConst.NpcLeaveMaxSpeed, wallMgr,
//                             () =>
//                             {
//                                 
//                             });
//
//                     }
//                     break;
//             }
//         }


        /// <summary>
        /// 触发检票事件树
        /// </summary>
        /// <param name="waitQueueIndex"></param>
        public void TriggerCheckTicketEventTree(int waitQueueIndex)
        {
            _waitQueueIndex = -1;
            _waitIndex = -1;
            _waitTimer = 0;
            _queueMoodStage = -1;
            
            int treeId = CityRealAiConst.CheckTicketEventTreeIds[waitQueueIndex];
            TreeConfig = _cfgMgr.GetAiEventTreeConfig(treeId);
            TreeState = CityRealEventTreeState.WaitMoveRoom;
            TreeType = CityRealEventTreeType.DrivingEventTree;
            TreeIsInterrupt = TreeConfig.is_interrupt;
            StartEventTree();
        }

        /// <summary>
        /// 执行下车事件
        /// </summary>
        /// <param name="getOffTransportPointIndex"></param>
        public void ExecuteGetOffTransport(int getOffTransportPointIndex)
        {
            if (_containerMgr is CityRealAiWallManager wallMgr)
            {
                IsAlive = true;
                getOffTransportPointIndex = Mathf.Min(getOffTransportPointIndex, wallMgr.GetOffTransportLocalPosList.Count - 1);
                Seeker.UpdatePos(wallMgr.GetWorldPos(wallMgr.GetOffTransportLocalPosList[getOffTransportPointIndex]));
                Seeker.transform.localEulerAngles = new Vector3(0, -45f, 0);
                _roleObj.SetActive(true);
                Seeker.PlayAni(CityRealAiConst.NpcGetOffTransportAniName, Vector3.zero);
                Timers.inst.Add(CityRealAiConst.NpcGetOffTransportAniTime, 1, _getOffTransportAniComplete);
            }
        }

        private void GetOffTransportAniComplete(object o)
        {
            TryExecuteEventTree();
        }

        /// <summary>
        /// 执行上车排队事件
        /// </summary>
        public void ExecuteGetOnTransportWaitQueue()
        {
            // npc来城门的目的就是排队上车，所以继续执行目标，城门内的确定第一个事件点的逻辑跟其他房间不一致
            // 城门内只有一种执行事件，当第一个事件点执行失败后，需要继续检测后续事件
            var eventInfo = TreeConfig.event_array[_curEventIndex];
            var eventId = (int) eventInfo.x;
            var pointInfo = _containerMgr.GetEventPointInfo(Uid, eventId, CityRealEventPointState.Idle);
            if (pointInfo == null) // 没有可以执行的事件点
            {
                PassiveBreakEventEnd();
                return;
            }

            pointInfo.UpdatePerformer(this);
            EventDispatch.UpdatePointInfo(pointInfo);
            
            StartEvent();
        }

        /// <summary>
        /// 执行上车事件
        /// </summary>
        public void ExecuteGetOnTransport(int getOnTransportPointIndex)
        {
            if (_containerMgr is CityRealAiWallManager wallMgr)
            {          
                getOnTransportPointIndex = Mathf.Min(getOnTransportPointIndex, wallMgr.GetOnTransportLocalPosList.Count - 1);
                if (IsAlive)
                {
                    EndEventTree();
                    Seeker.InRoomStartMove(Uid, wallMgr.ContainerId, wallMgr.GetOnTransportLocalPosList[getOnTransportPointIndex], CityRealAiConst.NpcDefaultMaxSpeed, wallMgr, GetOnTransportEventEnd);
                }
                else
                {
                    GetOnTransportEventEnd();
                }
            }
        }

        private void GetOnTransportEventEnd()
        {
            Seeker.PlayAni(CityRealAiConst.NpcGetOnTransportAniName, new Vector3(0, 135f, 0));
            Timers.inst.Add(CityRealAiConst.NpcGetOnTransportAniTime, 1, _getOnTransportAniComplete);
        }

        private void GetOnTransportAniComplete(object o)
        {
            if (_containerMgr is CityRealAiWallManager wallMgr)
            {
                IsAlive = false;
                _roleObj.SetActive(false);
                wallMgr.NpcGetOnTransportComplete(this);
            }
        }

        // 雇佣后移除区域雇员小人
        public void RemoveStaffNpc()
        {
            var staffDic = CityRealAiManager.GetInstance().HudMgr.StaffDic;
            if (staffDic.ContainsKey(Uid))
            {
                staffDic[Uid].DestroyHudShow();
            }
            RemoveFromContainer();
            Dispose();
        }

        public override void Dispose()
        {
            if (Timers.inst.Exists(_getOffTransportAniComplete))
            {
                Timers.inst.Remove(_getOffTransportAniComplete);
            }
            if (Timers.inst.Exists(_getOnTransportAniComplete))
            {
                Timers.inst.Remove(_getOnTransportAniComplete);
            }
            if (Timers.inst.Exists(_getOnBusAniComplete))
            {
                Timers.inst.Remove(_getOnBusAniComplete);
            }
            if (Timers.inst.Exists(_getOffBusAniComplete))
            {
                Timers.inst.Remove(_getOffBusAniComplete);
            }
            base.Dispose();
            
        }
    }
}
